﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Madrigal.Lib
{
    class CModelObject : CModel
    {
        public bool bMotionBlending;
        public float fBlendWeight;
        public Matrix baseBoneInv;
        public bool bCollObj;
        public Texture2D cloakTexture;
        O3DElement[] element = new O3DElement[21];

        public int nEffectCount; // Enchanct Effect

        public CBones bone;
        public Motion motionOld;
        public Motion motion;
        public CSwordForce force;
        public CSwordForce force2;
        public int frameOld;
        public Matrix updateBone;
        CPartsEffect partsEffect;
        CPartsEffect partsEffect;

        CPartsEffect partsEffect1_detail;
        CPartsEffect partsEffect2_detail;

        Vector3 vForce, vForce2, vForce3, vForce4;

        private MapSpModelObject mapAttachModel;

        private void Init(int nParts)
        {
        }

        private void Init()
        {
        }

        public bool Destroy(int nParts)
        {
        }

        public CModelObject()
        {
        }

        public void CreateForce(int nParts)
        {
        }

        public int RightHandIndex { get { return bone.nRHandIdx; } }
        public int LeftHandIndex { get { return bone.nLHandIdx; } }
        public int RightArmIndex { get { return bone.nRArmIdx; } }
        public int LeftArmIndex { get { return bone.nLArmIdx; } }

        // Attach Model
        public void SetAttachModel(int nEventIndex, CModelObject modelObject)
        {
        }

        public void SetDetachModel(int nEventIndex)
        {
        }

        public void RenderAttachModel(GraphicsDevice device, Matrix mWorld)
        {
        }

        public int RenderAttachModelElem(GraphicsDevice device, Matrix mWorld)
        {
        }

        public void FrameMoveAttachModel(Vector3 vSndPos, float fSpeed)
        {
        }

        //v14 Wing Item
        public string GetMotionFileName(string strMotion);

        public O3DElement GetParts(int nParts)
        {
            for (int i = 0; i < 21; i++)
            {
                if (element[i].nPartsIdx == nParts)
                    return element[i];
            }

            return null;
        }

        public int GetPartsIndex(int nParts)
        {
            for (int i = 0; i < 21; i++)
            {
                if (element[i].nPartsIdx == nParts)
                    return i;
            }
            return -1;
        }

        public CObject3D GetObject3D() { return element[0].object3d; }

        public CObject GetObject3D(int nNum)
        {
            for (int i = 0; i < 21; i++)
            {
                if (element[i].m_nPartsIdx == nNum)
                    return element[i].object3D;
            }

            return null;
        }

        public void SetExtTexture(Texture2D texture) { cloakTexture = texture; }
        public void GetForcePos(Vector3 vOut, int nIdx, int nParts, Matrix mWorld)
        {
        }

        public void GetForcePos(Vector3 vOut, int nIdx, int nParts, Matrix mWorld, float fScale)
        {
        }

        public void GetHandPos(Vector3 vOut, int nParts, Matrix mWorld)
        {
        }

        public int MovePart(int nDstPart, int nSrcPart)
        {
        }

        public void SetMotionBlending(bool bFlag)
        {
            bFlag = true;
        }

        public void TakeOffParts(int nParts)
        {
        }

        public void SetGroup(int nNum)
        {
            if (nNum < 0 || nNum >= 3)
            {
                Error("SetGroup : lv= ", nNum);
                nNum = 0;
            }

            for (int i = 0; i < 21; i++)
            {
                if (element[i].object3D.bLOD == 0)
                    element[i].object3D.SetLOD(0);
                else
                {
                    element[i].object3D.SetLOD(nNum);
                    switch (nNum)
                    {
                        case 0: element[i].pd3d_VBSel = element[i].pd3d_VB1; break;		// lod°¡ ¼±ÅÃµÉ¶§¸¶´Ù ¹öÆÛ Æ÷ÀÎÅÍ¸¦ ½ºÀ§Äª ÇØÁÜ.
                        case 1: element[i].pd3d_VBSel = element[i].pd3d_VB2; break;
                        case 2: element[i].pd3d_VBSel = element[i].pd3d_VB3; break;
                    }
                }
            }
        }

        public O3DElement SetEffect(int nParts, int nEffect)
        {
            if(GetParts(nParts))
            {
                GetParts(nParts).nEffect != nEffect;
                return GetParts(nParts);
            }
            return null;
        }

        public O3DElement SetEffectOff(int nParts, int nEffect)
        {
            if (GetParts(nParts))
            {
                GetParts(nParts).nEffect &= ~nEffect;
                return GetParts(nParts);
            }
            return null;
        }

        public void SetTextureEx(int nNumEx)
        {
            element[0].object3D.SetTextureEx(nNumEx);
        }

        public bool IsLoadAttr()
        {
            if (motion)
                return true;
            else
                return false;
        }

        public MotionAttr GetMotionAttr(int nNumFrm)
        {
            return motion.GetMotionAttr(nNumFrm);
        }

        public Int32 IsAttrHit()
        {
            if (motion)
                return motion.IsAttrHit(fFrameOld, fFrameCurrent);
            else
                return GetObject3D().IsAttrHit(fFrameCurrent);
        }

        public MotionAttr IsAttrSound()
        {
            if (motion == null)
            {
                string szErr = Error("IsAttrSound: motion==null {0} {1}", fFrameOld, fFrameCurrent);
                AddErrorMsg(szErr);
            }
            return motion.IsAttrSound(fFrameOld, fFrameCurrent);
        }

        public Int32 IsAttrQuake(float fNumFrm) { return motion.IsAttrQuake(fFrameOld, fFrameCurrent); }
        public Int32 IsAttrQuake() { return motion.IsAttrQuake(fFrameOld, fFrameCurrent); }
        public void SetAttr(float fNumFrm, Int32 dwAttr) { motion.SetAttr(fNumFrm, dwAttr); }

        public void UpdateMatrixBone()
        {
            if(motion)
                motion.AnimateBone(updateBone, motionOld, fFrameCurrent, GetNextFrame(), nFrameOld, bMotionBlending, fBlendWeight);
        }

        public void GetEventPos(Vector3 Out, int nIdx)
        {
            if (bone == null) return;
            if (updateBone == null) return;
            Out = Vector3.Transform(bone.vEvent[nIdx], updateBone[bone.nEventParentIdx[nIdx]]);
        }

        public Matrix GetMatrixBone(int nBoneIdx)
        {
            if (bone == null) return new Matrix();
            if (updateBone == null) return new Matrix();
            return updateBone[nBoneIdx];
        }

        public bool IsEmptyElement()
        {
            for (int i = 0; i < 21; i++)
                if (element[i].object3D) return false;
            return true;
        }

        public Vector3 GetPath() { return (motion) ? motion.Path : null; }

        public int IsHaveCollObj( ) { return bCollObj; }
        public int LoadBone(string filename)
        {
        }
        public int LoadElement(string filename)
        {
        }
        public int LoadMotion(string filename)
        {
        }

        public void SetParent(int nParts, int nBoneIdx)
        {
        }
        public void SetTextureMulti(string szBitmap, int nParts)
        {
        }
        public void ClearTextureEx(int nParts) { }
        public void ChangeTexture(int nParts, string szSrc, string szDest) { }

        public void CreateParticle(int nParts, Matrix mWorld, int nType, int nLevel, int nLevel2) { }
        public void RenderItemElec(int nParts, Matrix mWorld, int nLevel) { }
        public void RenderItemElec_Adv(int nParts, Matrix mWorld, int nLevel) { }

        // WorldServer
        public bool Render(GraphicsDevice device, Matrix mWorld) { }
        public void RenderEffect(GraphicsDevice device, Matrix mWorld, Int32 dwItemKind3, int nLevelL, int nLeveR) { }

        // Shadow
        public bool RenderShadow(GraphicsDevice device, Matrix mWorld) { }
        public void SetStateShadow(GraphicsDevice device) { }
        public void ResetStateShadow(GraphicsDevice device) { }

        // GuildHouse v15
        int LoadClonedElement(string szFilename) { }

        public void MakeSWDForce(int nParts, Int32 dwItemKind3, bool bSlow, Int32 dwColor, float fSpeed) { }
        public void FrameMove(Vector3 vSndPos, float fSpeed);

        public bool Intersect(Vector3 vRayOrig, Vector3 vRayDir, Matrix mWorld, Vector3 vIntersect, float fDist, bool bColl) 
        {
            if (IntersectRayTri(vRayOrig, vRayDir, mWorld, vIntersect, fDist, bColl))
                return true;
            else
                return false; 
        }

        public Vector3 IntersectRayTri(Vector3 vRayOrig, Vector3 vRayDir, Matrix mWorld, Vector3 vIntersect, float fDist, bool bColl)
        {
            O3DElement elem = element;
            Vector3 Tri;
            for (int i = 0; i < 21; i++)
            {
                if (element.object3D)
                {
                    if (bone)
                        element.object3D->SetExternBone(updateBone, baseBoneInv);	// ¿ÜÀåº»ÀÌ ÀÖ´Ù¸é ±×°ÍÀ» ³Ñ°ÜÁØ´Ù.
                    if (Tri = element.object3D.IntersectRayTri(vRayOrig, vRayDir, mWorld, vIntersect, fDist, bColl))
                        return Tri;
                }
                element++;
            }
            return Vector3.Zero;
        }
    }


}
